<?php

/**
 * contact : 刘经理 19326416371
 * company : 版权所属 四川北星惯牌科技有限公司
 **/

namespace app\common\manager\prepay\gateway;

use addons\epay\library\Service;
use app\common\library\InviteCode;
use app\common\manager\BaseManager;
use app\common\manager\MatchManager;
use app\common\manager\OrderManager;
use app\common\manager\PayLogManager;
use app\common\manager\UserAccountManager;
use app\common\model\Coupon;
use app\common\model\Member;
use app\common\model\Order;
use app\common\model\SignUp;
use app\common\model\UserAccount;
use app\common\model\UserCoupon;
use think\Db;
use think\Exception;

class Match
{
    CONST METHOD = 'Match';

    CONST TYPE_ALIPAY = 1;
    CONST TYPE_WECHAT = 2;
    public function order($user, $request,$isTrans=true)
    {
        if ($isTrans)
            Db::startTrans();
        try {
            $prePayment = null;
            $type = $request['type'] ?? 'wechat';
            $orderId = $request['orderId'] ?? '';
            $method = $request['method'] ?? 'JSAPI';
            $relationId = $request['relationId'] ?? 0;
            $is_balance = $request['isBalance'] ?? 0;
            $userCouponId = $request['userCouponId'] ?? 0;
            $signId = $request['signId'] ?? 0;
            if (!$user->is_authentication){
                throw new Exception('您未实名认证，无法操作');
            }

            $userCouponInfo = null;
            $orderInfo = Order::where('po_id',$orderId)->where('type',Order::TYPE_MATCH)->find();
            if (!$orderInfo) {
                if ($userCouponId) {
                    $userCouponInfo = UserCoupon::where('id', $userCouponId)->where('user_id', $user->id)->find();
                    if (!$userCouponInfo) {
                        throw new Exception('优惠券信息有误，无法使用');
                    }

                    if ($userCouponInfo['expires_time'] < time()) {
                        throw new Exception('优惠券已过期，无法使用');
                    }

                    if ($userCouponInfo['detail'] != Coupon::DETAIL_MATCH) {
                        throw new Exception('优惠券类型有误，无法使用');
                    }

                    if ($userCouponInfo['block'] == UserCoupon::BLOCK_YES) {
                        throw new Exception('优惠券已被使用，无法使用');
                    }

                }
            }else{
                $userCouponId = $orderInfo['user_coupon_id'] ?? 0;
                $userCouponInfo = UserCoupon::where('id', $userCouponId)->where('user_id', $user->id)->find();
            }
            if (!$relationInfo = \app\common\model\Match::where('m_id',$relationId)->find()) {
                throw new Exception('关联订单信息不存在');
            }

            if ($relationInfo['people_count'] <=  $relationInfo['join_count']){
                throw new Exception('当前赛事已满员，无法参与');
            }

            if ($relationInfo['sign_start_date'] > time()) {
                throw new Exception('当前赛事报名时间未开始，无法参与');
            }

            if ($relationInfo['sign_end_date'] < time()) {
                throw new Exception('当前赛事报名时间已结束，无法参与');
            }

            if ($relationInfo['cost'] < 0.01){
                throw new Exception('订单金额有误，无法创建订单');
            }

            if(!$signId){
                throw new Exception('请选择名片');
            }else if (!$signInfo = SignUp::where('id',$signId)->where('user_id',$user->id)->find()) {
                throw new Exception('当前名片信息有误，请正确操作');
            }
            $time_expire = config('app.time_expire') ?? 5;
            $time_expire = bcadd(time(), bcmul($time_expire,60));
            if ($type == 'wechat'){
                $time_expire = date('YmdHis', $time_expire);
            }else if ($type == 'alipay'){
                $time_expire = date('Y-m-d H:i:s', $time_expire);
            }

            /**
             * 如果已下单 ，将无法再下单
             * 如果有已下单未支付的订单，将重新拉起未支付订单
             *
             */
            if (Order::where('user_id',$user->id)->where('type',Order::TYPE_MATCH)->where('relation_id',$relationId)->where('pay_state',Order::PAY_STATE_SUCCESS)->count()) {
                throw new Exception('已下单，无法重复下单');
            }

            /**
             * 如果传参orderId ,在上面条件通过的情况下，将拉起传参过来的订单
             */
            $pref_amount = 0.00;
            if ( !empty($orderInfo) && $orderInfo['expire_time'] > time()) {
                $real_money = bcadd($orderInfo['real_money'],0,2);
                $order = $orderInfo['order'];
                $orderData = ['id'=>$orderId,'time_expire'=>$orderInfo['expire_time']];
                $result['code'] = BaseManager::$successCode;
                $result['message'] = BaseManager::$successMessage;
                $result['data'] = $orderData;
                $prePayment = json_decode($orderInfo['pre_payment'],true);
            }else{
                $money = $real_money = bcadd($relationInfo['cost'],0,2);
                if($userCouponInfo){
                    if ($userCouponInfo['limit_amount'] > $money){
                        throw new Exception('当前金额未满足优惠券使用条件，无法使用');
                    }

                    if($userCouponInfo['type'] == Coupon::TYPE_FULL){
                        $real_money = bcsub($money,$userCouponInfo['amount'],2);
                        $pref_amount = $userCouponInfo['amount'];
                    }else if ($userCouponInfo['type'] == Coupon::TYPE_DISCOUNT && $userCouponInfo['rate'] > 0){
                        $real_money = bcdiv(bcmul($money,$userCouponInfo['rate'],2),100,2);
                        $pref_amount = bcsub($money,$real_money,2);
                    }

                    if (!UserCoupon::where('id', $userCouponId)->update(['block' => UserCoupon::BLOCK_YES,'update_time'=>time()])){
                        throw new Exception('优惠券使用失败，请稍后再试');
                    }
                }
                $order = orderNum();
                $data['order'] = $order;
                $data['user_id'] = $user->id;
                $data['order_money'] = $money;
                $data['real_money'] = $real_money;
                $data['user_coupon_id'] = $userCouponInfo['id']??0;
                $data['pref_money'] = $pref_amount;
                $data['relation_id'] = $relationId;
                $data['is_balance'] = $is_balance;
                $data['expire_time'] = strtotime($time_expire);
                $data['extend_param'] = serialize(['signId'=>$signId]);
                $data['ct_date'] = time();
                if (!\app\common\model\Match::where(['m_id'=>$relationId,'order_count'=>Db::raw('order_count < people_count')])->update(['order_count'=>Db::raw('order_count + 1'),'up_date'=>time()])) {
                    throw new Exception('当前人数预下单数量已满，无法下单');
                }
                $result = OrderManager::Order($user,$data,\app\common\model\Order::TYPE_MATCH,false);
                $result['data']['time_expire'] = strtotime($time_expire);
            }

            if ($is_balance && $result['code']==OrderManager::$successCode){
                $userAccount = UserAccount::where('user_id',$user->id)->find();
                if (!$userAccount){
                    throw new Exception('当前用户账户信息有误，无法使用此功能');
                }

                if ($userCouponInfo){
                    if (!UserCoupon::where('id', $userCouponId)->update(['block' => UserCoupon::BLOCK_NO,'status'=>UserCoupon::STATUS_USED,'update_time'=>time()])){
                        throw new Exception('优惠券使用失败，请稍后再试');
                    }
                }


                $result2 = UserAccountManager::money($user->id,$real_money,UserAccountManager::CHANGE_TYPE_PAYMENT,time(),UserAccountManager::TYPE_MATCH,['relation_id'=>$result['data']['id']],false);
                if ($result2['code']!=UserAccountManager::$successCode){
                    throw new Exception($result2['message']);
                }
                $resUpdate = ['pay_state'=>Order::PAY_STATE_SUCCESS,'pay_date'=>time(),'up_date'=>time()];
                $resultOrder = OrderManager::modify($result['data']['id'],$resUpdate,false);
                if ($resultOrder['code']!=OrderManager::$successCode){
                    throw new Exception($resultOrder['message']);
                }

                $upgradeResult = UserAccountManager::LevelUpgrade($user->id,'upgrade',false);
                if ($upgradeResult['code']!=UserAccountManager::$successCode){
                    throw new Exception($upgradeResult['message']);
                }

                if (!UserAccount::where(['user_id'=>$user->id])->update([
                    'join_count'=>Db::raw('join_count + 1'),
                    'match_count'=>Db::raw('match_count + 1'),
                    'version'=>Db::raw('version + 1')
                ])) {
                    throw new Exception('账户消费金额累加失败');
                }


                $specialResult = MatchManager::specialModify($relationId,false);
                if ($specialResult['code']!=MatchManager::$successCode){
                    throw new Exception($specialResult['message']);
                }

                $inviteCode = new InviteCode();
                $invite = $inviteCode->enCode();

                $matchJoiner = [
                    'match_id'=>$relationId,
                    'user_id'=>$user->id,
                    'order_id'=>$result['data']['id'],
                    'verify_code'=>$invite,
                    'real_name'=>$signInfo['real_name'],
                    'mobile'=>$signInfo['mobile'],
                    'state'=>Member::STATE_SUCCESS,
                    'pay_state'=>Member::PAY_STATE_SUCCESS,
                    'sign_id'=>$signId,
                    'backend_system'=>Member::BACKEND_SYSTEM_NO,
                    'create_time'=>time(),
                    'update_time'=>time()
                ];
                $joinerResult = MatchManager::MatchJoinerInsert($relationId,$matchJoiner,false);
                if ($joinerResult['code']!=MatchManager::$successCode){
                    throw new Exception('赛事人员信息创建失败，订单取消');
                }

                if ($isTrans)
                    Db::commit();
                $prePayment = null;

            }else{
                if (!$prePayment){
                    $result1 = PayLogManager::record(['user_id'=>$user->id,'method'=>self::METHOD,'type'=> $type=='alipay' ? self::TYPE_ALIPAY : self::TYPE_WECHAT,'order'=>$order,'money'=>$real_money,'create_time'=>time()]);
                    $returnUrl = \config('app.returnUrl');
                    if ($type=='wechat'){
                        $notifyUrl = \config('app.notifyWechatUrl');
                    }else if ($type=='alipay'){
                        $notifyUrl = \config('app.notifyAlipayUrl');
                    }
                    if ($result['code'] == OrderManager::$successCode && $result1['code'] == PayLogManager::$successCode) {
                        if ($isTrans)
                            Db::commit();

                        //file_put_contents('a.txt',$notifyUrl,FILE_APPEND);
                        $prePayment = Service::submitOrder($real_money,$order,$type,\app\common\model\Order::TYPE_ARRAY[\app\common\model\Order::TYPE_MATCH]['name'],$notifyUrl,$returnUrl,$method,$user->open_id,$time_expire,['relation_id'=>$relationId]);
                        $resUpdate = ['pre_payment'=>$prePayment,'up_date'=>time()];
                        $resultOrder = OrderManager::modify($result['data']['id'],$resUpdate,false);
                        if ($resultOrder['code']!=OrderManager::$successCode){
                            throw new Exception('订单信息修改失败');
                        }
                        if($result1['data']['id']){
                            $id = $result1['data']['id'];
                            $update = ['request'=>serialize($prePayment)];
                            PayLogManager::modify($id,$update);
                        }
                    }else{
                        throw new Exception($result['message'].'或'.$result1['message']);
                    }
                }

            }
            return ['code'=>1,'message'=>'success','data'=>['order'=>$result['data'],'pre_payment'=>$prePayment]];
        }catch (Exception $exception){
            if ($isTrans)
                Db::rollback();
            return ['code'=>0,'message'=>$exception->getMessage(),'data'=>null];
        }
    }
}